#
# ABSTRACT FACTORY EXERCISE
# 
# January, 2013
require 'singleton'

class Client
  attr_accessor :factory
	def initialize (factory)
    @factory = factory.instance.register
  end

  def factory=(factory)
    @factory = factory.instance.register
  end

	def foo
    @prod_A = @factory.createProductA
		@prod_A.perform
		my_prod_B = @factory.createProductB
		my_prod_B.perform
		@prod_C = @factory.createProductC
		@prod_C.perform
    @prod_D = @factory.createProductD
    @prod_D.perform

	end
end

class ProductA
  def perform
    puts "I'm a ProductA, doing my stuff"
  end
end

class ProductB
  def perform
    puts "I'm a ProductB, doing it"
  end
end

class ProductC
  def perform
    puts "I'm a ProductC, performing"
  end
end

class ProductD
  def perform
    puts "I'm a ProductD, performing"
  end
end

class CoolProductA
  def perform
    puts "I'm a cool ProductA, doing my stuff"
  end
end

class CoolProductB
  def perform
    puts "I'm a cool ProductB, doing it"
  end
end

class CoolProductC
  def perform
    puts "I'm a cool ProductC, performing"
  end
end

class CoolProductD
  def perform
    puts "I'm a cool ProductD, performing"
  end
end

class DeadlyProductA
  def perform
    puts "I'm a deadly ProductA"
  end
end

class DeadlyProductB
  def perform
    puts "I'm a deadly ProductB"
  end
end

class DeadlyProductC
  def perform
    puts "I'm a deadly ProductC"
  end
end

class DeadlyProductD
  def perform
    puts "I'm a deadly ProductD"
  end
end


class Factory
  include Singleton

  def register factory
    @factory = factory
  end

end

class ProductFactory < Factory

  def createProductA
    ProductA.new
  end
  def createProductB
    ProductB.new
  end
  def createProductC
    ProductC.new
  end
  def createProductD
    ProductD.new
  end
  def register
    Factory.instance.register self
  end
end

class CoolProductFactory < Factory

  def createProductA
    CoolProductA.new
  end
  def createProductB
    CoolProductB.new
  end
  def createProductC
    CoolProductC.new
  end
  def createProductD
    CoolProductD.new
  end
  def register
    Factory.instance.register self
  end
end

class DeadlyProductFactory < Factory

  def createProductA
    DeadlyProductA.new
  end
  def createProductB
    DeadlyProductB.new
  end
  def createProductC
    DeadlyProductC.new
  end
  def createProductD
    DeadlyProductD.new
  end
  def register
    Factory.instance.register self
  end
end




my_client = Client.new ProductFactory
my_client.foo
my_client.factory = CoolProductFactory
my_client.foo
my_client.factory = DeadlyProductFactory
my_client.foo
